/**
 * @file print.c
 * contains all methods to print information about files
 *
 * @author ic14b040 Markus Scharitzer <ic14b040@technikum-wien.at>
 * @author ic14b035 Siegfried Becher <ic14b035@technikum-wien.at>
 * @author ic14b004 Helene Wiesinger <ic14b004@technikum-wien.at>
 * @date 2015/3/13
 *
 * @version 1 
 *
 * 
 *
 */

/*
 * -------------------------------------------------------------- includes --
 */
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include "print.h"

/**
 *
 * \brief print_info function
 * prints information how to use the myfind
 *
 * \param argv program arguments for error handling
 * \return void
 **/
void print_info(const char * const * argv) {
	if(!fprintf(stdout, "use myfind the right way: myfind <path> [args]\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "possible arguments:\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-user	<name>/<uid> 	finde Directoryeinträge eines Users\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-name	<pattern> 	finde Directoryeinträge mit passendem Namen\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-type	[bcdpfls] 	finde Directoryeinträge mit passendem Typ\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-print		gibt den Namen des Directoryeintrags aus\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));   
		exit(1);
	}
	if(!fprintf(stdout, "-ls		gibt die Nummer des Inodes, Anzahl der Blocks, Permissions, Anzahl der Links, Owner, Group, Last Modification Time und den Namen des Directoryeintrags aus.\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-nouser		finde Directoryeinträge ohne User\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
	if(!fprintf(stdout, "-path	<pattern> 	finde Directoryeinträge mit passendem Pfad (inkl. Namen)\n")){
		fprintf (stderr, "%s: print failed '%s'\n", argv[0], strerror (errno));  
		exit(1);
	}
}	

/**
*\brief print function
*
* prints the filename to the standardoutput
*
*\param name: name of the current file
*
* \param argv program arguments for error handling
*\return void
*/
void print(const char * const * argv,char *name)
{	
  if(!fprintf(stdout, "%s\n", name)){
	fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror (errno));  
	}
}

/**
 *
 * \brief print_ls function
 *
 * prints information about the found file
 *
 * \param argv program arguments for error handling
 * \param name: name of the current file
 *
 * \return void
 *
 */
void print_ls(const char * const * argv,char *name)
{
  struct stat buf;
  
  char    modestr[11];
  time_t rawtime;
  struct tm *info;
  char time_buffer[80];
  if (lstat(name, &buf) == -1)
    {
      fprintf (stderr, "%s lstat failed '%s': %s\n",
	       argv[0], name, strerror (errno));  
    }
  else
    {

      long blocks = 0;      
		if (!getenv("POSIXLY_CORRECT"))
		{
			blocks = (long)buf.st_blocks / 2;
		}
		else{
			blocks = (long)buf.st_blocks;
		}
      rawtime=buf.st_mtime;
      if(!(info = localtime( &rawtime ))){
		 fprintf (stderr, "%s localtime failed '%s': %s\n",
	         argv[0], name, strerror(errno));  
	}
      strftime(time_buffer,80,"%b %d %H:%M", info);

      get_mode_string( buf.st_mode, modestr );
	if(!fprintf(stdout, "%d "	, (int) buf.st_ino)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%6ld "	, blocks)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%s "    , modestr)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%4d "  , (int) buf.st_nlink)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%-8s " , uid_name(buf.st_uid))){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%-8s " , gid_name(buf.st_gid))){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%8ld " , (long)buf.st_size)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, "%s",  time_buffer)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}
	if(!fprintf(stdout, " %s"  , name )){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
	}

      if(S_ISLNK(buf.st_mode)){
	char * link = (char *) malloc(sizeof(char)*(buf.st_size+2));
	int outcome = 0;
	if((outcome = readlink(name, link, buf.st_size+2))==-1){
		fprintf(stderr, "readlink failed '%s': %s\n",
	       name, strerror (errno));
	}
	else{
        /* der name des files, auf das ein link verweist ist nicht nullterminiert. */
	*(link+outcome) = '\0';	
		if(!fprintf(stdout, "->%s", link)){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
		}		
	
	}
	free(link);

    }
		if(!fprintf(stdout, "\n")){
		fprintf (stderr, "%s: print failed '%s': %s\n", argv[0], name, strerror(errno));  
		
	}

    }
}

/**
 *
 * \brief uid_name function
 *
 * using getpwuid the uid is changed to a name
 *
 * \param uid: uid_t from struct stat
 *
 * \return char * - if getpwuid is NULL the uid is returned
 *
 */	
char * uid_name(uid_t uid)
{
  /* fixed  error: function declaration isn’t a prototype [-Werror=strict-prototypes] 
     struct passwd *getpwuid(), *pw_ptr;
     function already declared in pwd.h
  */
  struct  passwd *pw_ptr;
  static  char numstr[10];

  if ( ( pw_ptr = getpwuid( uid ) ) == NULL ){
    sprintf(numstr,"%d", uid);
    return numstr;
  }
  else
    return pw_ptr->pw_name ;
}

/**
 *
 * \brief get_mode_string function
 *
 * puzzles the mode to an awesome, clear string for the -ls function
 *
 * \param mode: st_mode from struct stat
 * \param str[]: target-string
 *
 * \return void
 *
 */
void get_mode_string(int mode, char str[])
{
  /*default - no permissions */
  strcpy( str, "----------" );           

  if ( S_ISDIR(mode) )  str[0] = 'd';    /* what are we dealing with? */
  if ( S_ISCHR(mode) )  str[0] = 'c';   
  if ( S_ISBLK(mode) )  str[0] = 'b';    
  if ( S_ISLNK(mode) )  str[0] = 'l';

  if ( mode & S_IRUSR ) str[1] = 'r';   /* 3 userbits */
  if ( mode & S_IWUSR ) str[2] = 'w';
  if ( mode & S_IXUSR ) str[3] = 'x';

  if ( mode & S_IRGRP ) str[4] = 'r';    /* 3 groupbits */
  if ( mode & S_IWGRP ) str[5] = 'w';
  if ( mode & S_IXGRP ) str[6] = 'x';

  if ( mode & S_IROTH ) str[7] = 'r';    /* 3 otherbits */
  if ( mode & S_IWOTH ) str[8] = 'w';
  if ( mode & S_IXOTH ) str[9] = 'x';
}

/**
 *
 * \brief gid_name function
 *
 * using getgrid the giid is changed to a name
 *
 * \param gid: gid_t from struct stat
 *
 * \return char * - if getgrid is NULL the uid is returned
 *
 */
char *gid_name(gid_t gid)
{
  /*  error: function declaration isn’t a prototype [-Werror=strict-prototypes] 
      struct group *getgrgid();
      function already declared in grp.h
  */
  struct group *grp_ptr;
  static  char numstr[10];

  if ( ( grp_ptr = getgrgid(gid) ) == NULL ){
    sprintf(numstr,"%d", gid);
    return numstr;
  }
  else
    return grp_ptr->gr_name;
}

/*
 * =================================================================== eof ==
 */
